package indus.icalendarFileGenerator;

import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.TimeZone;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *  An Event class with "setter" methods that prompt a user to
 *  set data for event fields and "getter" methods that return 
 *  the data for event fields.
 *
 *  @author Team Indus
 *  @date August 13th 2014
 *  @bugs None
 */
public class Event {
	
	private String GEO;
	private String status;
	private String version;
	private String summary;
	private String timeZoneIdentifier;
	private String location;
	private String classification;
	private String priorityValue;
    private String startDate;
    private String startDateIcsFormat;
	private String endDateIcsFormat;
	private String reoccurrenceText;
    private String startTimeIcsFormat;
	private String endTimeIcsFormat;
	private int startTime;
	private Scanner userInput;
   
   
   /**
    * Constructor
    */
  public Event(){
    this.GEO = "";
    this.status = "";
    this.version = "";
    this.summary = "";
    this.timeZoneIdentifier = "";
    this.location = "";
    this.classification = "";
    this.priorityValue = "";
    this.startDate = "";
    this.startDateIcsFormat = "";
    this.endDateIcsFormat = "";
    this.reoccurrenceText = "";
    this.startTimeIcsFormat = "";
    this.endTimeIcsFormat = "";
    this.startTime = 0;
    userInput = new Scanner(System.in);
  }
	
	
	/**
	 * Sets the GEO for the event
	 *  
	 *  @param 	Void
	 *  @return	Void
	 */	
	public void setGEO() {
		
		this.GEO = "21.445634;-157.918854";
	}
	
	
	/**
	 * Returns the GEO for the event
	 *  
	 *  @param 	Void
	 *  @return	GEO string
	 */	
	public String getGEO() {
		return this.GEO;
	}
	
	/**
	 * Sets the status of the event
	 *  
	 *  @param 	Void
	 *  @return	Void
	 */	
	public void setStatus() {
		
		this.status = "CONFIRMED";
	}
	
	
	/**
	 * Returns the status of the event
	 *  
	 *  @param 	Void
	 *  @return	The status string
	 */	
	public String getStatus() {
		
		return this.status;
	}
	
	/**
	 *  Sets the version of the event
	 *  
	 *  @param 	Void
	 *  @return	Void
	 */	
	public void setVersion() {
		
		this.version = "2.0";
	}
	
	/**
	 *  Returns the version of the event
	 *  
	 *  @param 	Void
	 *  @return	The version of the event
	 */	
	public String getVersion() {
		
		return this.version;
	}
	
	
	/**
	 *  Prompts a user to enter data for summary field and
	 *  sets retrieved data as this events summary.  
	 *  
	 *  @param 	Void
	 *  @return	Void
	 */	
	public void setSummary() {
		
		String summary = "";

		System.out.print("Please enter the title of the event: ");
		summary = userInput.nextLine();
		
		this.summary = summary;
	}

	/**
	 *  Returns the summary for this event. 
	 *  
	 *  @param 	 Void
	 *  @return  Returns the summary for this event. 
	 */	
	public String getSummary() {
		
		return this.summary;
	}

	/**
	 *  Prompts a user to enter data for location field and
	 *  sets retrieved data as this events location.  
	 *  
	 *  @param  Void
	 *  @return Void
	 */
	public void setLocation() {
		
		String location = "";
		
		System.out.print("Please enter the location of the event: ");
		location = userInput.nextLine();

		this.location = location;
	}

	/**
	 *  Returns the location for this event. 
	 *  
	 *  @param 	 Void
	 *  @return  Returns the location for this event. 
	 */	
	public String getLocation() {
		
		return this.location;
	}

	/**
	 *  Sets the time zone for this event. 
	 *  
	 *  @param Void
	 *  @return Void
	 */
	public void setTimeZoneIdentifier() {
		
		TimeZone tz = TimeZone.getDefault();
		
		this.timeZoneIdentifier = tz.getID();
	}

	/**
	 *  Returns the time zone for this event. 
	 *  
	 *  @param	 Void
	 *  @return  Returns the time zone for this event. 
	 */
	public String getTimeZoneIdentifier() {
		
		return this.timeZoneIdentifier;
	}

	/**
	 *  Prompts a user to enter data for classification field 
	 *  and sets retrieved data as this events classification.  
	 */	
	public void setClassification() {
		
		boolean done = false;
		int classificationValue = 1;
		
		//do-while loop to get valid input
		do {
		    
			try {    
				System.out.print("Please select a privacy setting (1 - 3): \n");
				System.out.println("(1) - Public\n(2) - Private\n(3) - Confidential\n");
				classificationValue = userInput.nextInt();
				
				if(classificationValue >= 1 && classificationValue <= 3) {
					
					this.userInput.nextLine();
					done = true;
			  }  
			  else {
			    
			    System.out.println("Sorry, please enter a valid integer.");
			    this.userInput.nextLine();
				  done = false;
			  }
		  }
		  catch(InputMismatchException ime) {
		    
		  	System.out.println("Sorry, please enter a valid integer.");
		   	this.userInput.nextLine();
		   	done = false;
	    }					
		}
		while (!(done)); //end of do-while	
			
		switch(classificationValue) {
		
		case 1:
			this.classification = "PUBLIC";
			break;
		case 2:
			this.classification = "PRIVATE";
			break;
		case 3:
			this.classification = "CONFIDENTIAL";
			break;
		default:
			this.classification = "PUBLIC";
			break;
		}
	}

	/**
	 *  Returns the classification of this event. 
	 *  
	 *  @return  Returns the classification of this event. 
	 */	
	public String getClassification() {
		
		return this.classification;
	}

	/**
	 *  Prompts a user to enter a value for priority field and
	 *  sets retrieved value as this events priority level.  
	 */	
	public void setPriorityValue() {
		
		boolean done = false;
		int priorityValue = 0;
		
		//do-while loop to get valid input
		do {
		    
			try {    
				System.out.print("Please enter a priority level (0 - 9): \n");
				System.out.println("(0) = None\n(1 - 4) = High\n(5) = Medium\n(6 - 9) = Low\n");
				priorityValue = userInput.nextInt();
				
				if(priorityValue >= 0 && priorityValue <= 9) {
					
					this.userInput.nextLine();
					done = true;    
				}  
			  else {
			    
			    System.out.println("Sorry, please enter a valid integer.");
			    this.userInput.nextLine();
					done = false;
			  }
		  }
		  catch(InputMismatchException ime) {
		      
		    System.out.println("Sorry, please enter a valid integer.");
		   	this.userInput.nextLine();
		   	done = false;
		  }					
		}
		while (!(done)); //end of do-while
		
		//Sets the string priority value to the string representation of the int priority value
		this.priorityValue = Integer.toString(priorityValue); 
	}

	/**
	 *  Returns the priority level of this event. 
	 *  
	 *  @return   Returns the priority level of this event.
	 */		
	public String getPriorityValue() {
		
		return this.priorityValue;
	}
   
	/**
	 *  Sets the start date for this event.  The date must be entered
	 *  in the following format: mm/dd/yyyy 
	 *  
	 *  IMPORTANT: this method must be called before setEndDate 
	 *  method is called, so setEndDate method has a date to 
	 *  check against (To find out if end date is on or after
	 *  start date)
	 */
	public void setStartDate() {
		
		boolean done = false;
		String startDate = "";
		
		// Get a valid date
		do {
		
			System.out.print("Start date (mm/dd/yyyy): ");
			startDate = this.userInput.nextLine();
			
			// Validate given date
			if(isValidDate(startDate)) {
				
				// Covert given date into ics format
				this.startDate = startDate;
				this.startDateIcsFormat = convertDateToIcsFormat(startDate);
				done = true;
			}
			
		}while(!done);
	}   

	/**
	 *  Returns the start date of this event in ics format.
	 *  
	 *  @return  the start date of this event in ics format.
	 */
	public String getStartDate() {
		
		return this.startDateIcsFormat;
	}

	/**
	 *  Sets the end date for this event.  The date must be entered
	 *  in the following format: mm/dd/yyyy 
	 *  
	 *  IMPORTANT: this method must be called after setStartDate 
	 *  so setEndDate method has a valid date to check against 
	 *  (To find out if end date is on or after start date)
	 */
	public void setEndDate() {
		
		boolean done = false;
		String endDate = "";
		
		// Get a valid date
		do {
		
			System.out.print("End date (mm/dd/yyyy): ");
			endDate = this.userInput.nextLine();
			
			// Validate given date
			if(isValidDate(endDate)) {
				
				SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
				
				try {
					Date testStartDate = sdf.parse(this.startDate);
					Date testEndDate = sdf.parse(endDate);
					
					// Check if given end date is after the start date
					if(testEndDate.after(testStartDate)) {
						
						// Covert given end date into ics format
						this.endDateIcsFormat = convertDateToIcsFormat(endDate);
						done = true;
					}
					else if(testEndDate.equals(testStartDate)) {
						
						// Covert given end date into ics format
						this.endDateIcsFormat = convertDateToIcsFormat(endDate);
						done = true;
					}
					else {
						
						System.out.println("Error: please enter a date that is on or after the start date.");
						done = false;
					}
						
				}
				catch (ParseException pe){
					
					System.out.println("Error: please enter a valid date.");
					done = false;
				}
			}
			
		}while(!done);
	}

	/**
	 *  Returns the end date of this event in ics format.
	 *  
	 *  @return  the end date of this event in ics format.
	 */
	public String getEndDate() {
		
		return this.endDateIcsFormat;
	}
   
	/**
	 *  Private method to help validate dates.
	 *  
	 *  @param   date - the date to validate.
	 *  @return  true if date is valid, false otherwise.
	 */
	private static boolean isValidDate(String date) {
		
		Date testDate = null;
		SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
		
		try {
			
			testDate = sdf.parse(date);
		}
		catch (ParseException pe){
			
			System.out.println("Error: please enter a date in the following format (mm/dd/yyyy).");
			return false;
		}
		
		if(!sdf.format(testDate).equals(date)) {
			
			System.out.println("Error: please enter a valid date.");
			return false;
		}
		
		return true;
	}

	/**
	 *  Private method to help covert dates to ics format.
	 *  
	 *  @param   date - the date to convert.
	 *  @return  dateIcsFormat - the date in ics format.
	 */
	private static String convertDateToIcsFormat(String date) {
		
		// Convert given date to the format: YYYYMMDD
		String dateIcsFormat = "";
		String[] splitDate;
		
		splitDate = date.split("/");
		dateIcsFormat = splitDate[2] + splitDate[0] + splitDate[1];
		
		return dateIcsFormat;
	}
   
	/**
	 *  Prompts a user to enter a value for the start time
	 *  of this event.  
	 */		
   	public void setStartTime() {
		
   		boolean done = false;
   		int startTime = 0;
   		
   		do {
   			
   			try {
   				
   	   			System.out.print("When did you want to start? Ex. 1500 = 3:00PM: ");
   	   		    startTime = userInput.nextInt();
   			
   				if(startTime % 100 > 59 || startTime > 2400 || startTime < 0) {
   					
   					System.out.println("You inputed an invalid time");
   				}
   				else {
   					
   					this.startTime = startTime;
   					this.startTimeIcsFormat = convertTimeToIcsFormat(startTime);
   					done = true;
   				}
   				
   			}
   			catch(InputMismatchException ime) {
   				
   				System.out.println("Error: Please enter an integer.");
   				this.userInput.nextLine();
   			}
			
   		}while(!done);
		
	}
 
	/**
	 *  Returns the value for the start time of this
	 *  event.
	 *  
	 *  @return the start time of this event.
	 */	  	
   	public String getStartTime() {
   		
   		return this.startTimeIcsFormat;
   	}
	
	/**
	 *  Prompts a user to enter a value for the end time
	 *  of this event.  
	 */  	
	public void setEndTime() {
		
		boolean done = false;
		int endTime = 0;
		
		do {
		
			try {
			
				System.out.print("When did you want to end? Ex. 1500 = 3:00PM: ");
				endTime = userInput.nextInt();
				
				if(this.startDateIcsFormat.equals(this.endDateIcsFormat) && endTime < this.startTime) {
					
					System.out.println("Your end time is earlier than your start time!");
				}
				else if(endTime % 100 > 59 || endTime > 2400 || endTime < 0) {
					
					System.out.println("You inputed an invalid time");
				}
				else {
					
   					this.endTimeIcsFormat = convertTimeToIcsFormat(endTime);
   					done = true;
				}
			}
			catch(InputMismatchException ime) {
				
   				System.out.println("Error: Please enter an integer.");
   				this.userInput.nextLine();
			}
			
		}while(!done);
	    //Clears scanner after method is done
		  if(userInput.hasNextLine()) {
				userInput.nextLine();
			}
	}

	/**
	 *  Returns the value for the end time of this
	 *  event.
	 *  
	 *  @return the end time of this event.
	 */	
	public String getEndTime() {
		
		return this.endTimeIcsFormat;
	}
	
	/**
	 *  Returns the a given time in Ics format.
	 *  
	 *  @return the given time in Ics format.
	 */	
	private String convertTimeToIcsFormat(int time) {
		
		String timeInIcsFormat = "";
		
		// If time is 0
		if(time == 0) {
			
			timeInIcsFormat = timeInIcsFormat+"0000";
		}
		// If time is 1000 or more
		else if(time >= 1000) {
			
			timeInIcsFormat = timeInIcsFormat+Integer.toString(time);
		}
		// if time is between 1 and 9
		else if(time >= 1 && time <= 9) {
			
			timeInIcsFormat = timeInIcsFormat+"000"+Integer.toString(time);
		}
		// If time is between 10 and 59
		else if(time >= 10 && time <= 59) {
			
			timeInIcsFormat = timeInIcsFormat+"00"+Integer.toString(time);
		}
		// If time is between 100 959
		else {
			
			timeInIcsFormat = timeInIcsFormat+"0"+Integer.toString(time);
			
		}
		return timeInIcsFormat;
	}
	/**
	 *  Builds the text line for a reoccurring event.
	 */		
	public void setReoccurrenceText() {
		
		boolean done = false;
		String isReccurring = "";
		String untilDate = "";
		
		do {
		
			try {
				
				System.out.print("Is this a reoccurring event? (y/n): ");
				isReccurring = this.userInput.nextLine();
				isReccurring.trim();
				isReccurring.toLowerCase();
			
				// if it is a recurring event
				if(isReccurring.compareTo("y") == 0) {
				
					// Ask to choose frequency
					try {
			
						this.reoccurrenceText = getFrequency();	
						untilDate = getUntilDate();
						this.reoccurrenceText = this.reoccurrenceText+"UNTIL="+untilDate+"\n";
						done = true;
				
					}
					catch(InputMismatchException ime) {
						System.out.println("Error: Please enter an interger.");
						this.userInput.nextLine();
					}
				}
				else if(isReccurring.compareTo("n") == 0) {
					
					done = true;
				}
				else {
					
					System.out.println("Error: Please enter y or n (y = yes, n = no).");
				}
			}
			catch(InputMismatchException ime) {
				System.out.println("Error");
				this.userInput.nextLine();
			}
			
		}while(!done);	
}

	/**
	 *  Returns the text line for a reoccurring event.
	 *  
	 *  @return the text line for a reoccurrin event.
	 */	
	public String getReoccurrenceText() {
		
		return this.reoccurrenceText;
	}

	/**
	 *  A private helper method used by public method
	 *  setReoccurrenceText.  Returns the end date of a
	 *  reoccurrence in Ics format.
	 *  
	 *  @return the end date of reoccurrence in Ics format.
	 */	
	private String getUntilDate() {
		
		boolean done = false;
		String untilDate;
		String untilDateIcsFormat = "";
		
		this.userInput.nextLine(); // Clear rubbish values from scanner
		// Get a valid date
		do {
		
			System.out.print("Repeat event till when? (mm/dd/yyyy): ");
			untilDate = this.userInput.nextLine();
			
			// Validate given date
			if(isValidDate(untilDate)) {
				
				SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
				
				try {
					Date testStartDate = sdf.parse(this.startDate);
					Date testEndDate = sdf.parse(untilDate);
					
					// Check if given end date is after the start date
					if(testEndDate.after(testStartDate)) {
						
						// Covert given end date into ics format
						untilDateIcsFormat = convertDateToIcsFormat(untilDate);
						done = true;
					}
					else if(testEndDate.equals(testStartDate)) {
						
						// Covert given end date into ics format
						untilDateIcsFormat = convertDateToIcsFormat(untilDate);
						done = true;
					}
					else {
						
						System.out.println("Error: please enter a date that is on or after the start date.");
					}
						
				}
				catch (ParseException pe){
					
					System.out.println("Error: please enter a valid date.");
				}
			}
			
		}while(!done);
		
		return untilDateIcsFormat;
	}

	/**
	 *  A private helper method used by public method
	 *  setReoccurrenceText.  Returns the beginning of the
	 *  reoccurrence text plus the value of representing how
	 *  frequent the event is to occur.
	 *  
	 *  @return the beginning of the reoccurrence text plus the
	 *          value of frequecy.
	 */	
	private String getFrequency() {
		
		boolean done = false;
		int frequency;
		String frequencyText = "";
		
		do {	
			
			try {
			
				System.out.println("(1) Daily\n(2) Weekly\n(3) Monthly");
				System.out.print("Frequency (1 - 3): ");
				frequency = this.userInput.nextInt();
		
				if(frequency >= 1 && frequency <= 3) {
			
					switch(frequency) {
			
					case 1:
						frequencyText = frequencyText+"RRULE:FREQ=DAILY;";
						break;
					case 2:
						frequencyText = frequencyText+"RRULE:FREQ=WEEKLY;";
						break;
					case 3:
						frequencyText = frequencyText+"RRULE:FREQ=MONTHLY;";
						break;
					default:
						frequencyText = frequencyText+"RRULE:FREQ=DAILY;";
						break;
					}
					done = true;
				}
				else {
					
					System.out.println("Error: Please enter an between 1 and 3.");
				}
			}
			catch(InputMismatchException ime) {
				
				System.out.println("Error: Please enter an integer.");
				this.userInput.nextLine();
			}
		}while(!done);	
		
		return frequencyText;
	}
}	 